#ifndef __ARQ_WINDOW_H__
#define __ARQ_WINDOW_H__

#include "arq.h"

// 窗口控制类模板
template <size_t BUFFER_SIZE = 1024>
class CARQSendWindow
{
    static constexpr size_t BUFFER_INDEX_MASK = BUFFER_SIZE - 1;
    static_assert((BUFFER_SIZE & BUFFER_INDEX_MASK) == 0, "BUFFER_SIZE is not power of 2");
public:
    CARQSendWindow()
    {

    }

    ~CARQSendWindow()
    {
        if (m_ppstUnAckMsg != nullptr)
        {
            delete [] m_ppstUnAckMsg;
            m_ppstUnAckMsg = nullptr;
        }
    }

    int32_t Init(uint32_t uiWndSize)
    {
        if (uiWndSize > BUFFER_SIZE)
        {
            // 设置窗口太大
            return -1;
        }

        m_ppstUnAckMsg = new (std::nothrow) ARQ_HEAD_S*[BUFFER_SIZE];
        if (m_ppstUnAckMsg == nullptr)
        {
            return -1;
        }

        m_uiWndSize = uiWndSize;

        return 0;
    }
    
    bool OnAck(uint32_t uiAckNo)
    {
        if (uiAckNo >= m_uiNextAckNo)
        {
            // 大的消息的AckNo都已经收到，可以确定小的消息也已经收到了
            m_uiNextAckNo = uiAckNo;

            return true;
        }

        return false;
    }

    void AddMsg(ARQ_HEAD_S* pstMsg)
    {
        pstMsg->uiSeqNo = m_uiNextSeqNo++;
        m_ppstUnAckMsg[pstMsg->uiSeqNo & BUFFER_INDEX_MASK] = pstMsg;
    }

    ARQ_HEAD_S* GetMsg(uint32_t uiSeqNo)
    {
        if (uiSeqNo < m_uiNextAckNo || uiSeqNo >= m_uiNextSeqNo)
        {
            return nullptr;
        }

        return m_ppstUnAckMsg[uiSeqNo & BUFFER_INDEX_MASK];
    }

    bool IsWndFull()
    {
        return (m_uiNextSeqNo - m_uiNextAckNo) > m_uiWndSize;
    }
    
private:
    ARQ_HEAD_S** m_ppstUnAckMsg = nullptr;
    uint32_t m_uiWndSize = 0;
    uint32_t m_uiNextAckNo = 0;
    uint32_t m_uiNextSeqNo = 0;
};

#endif //__ARQ_WINDOW_H__